package models

import (
	"fmt"
	"github.com/jinzhu/gorm"
	"strconv"
	"test/system"
	"time"

	// _ "github.com/mattn/go-sqlite3"
	_ "github.com/go-sql-driver/mysql"
)




var DB *gorm.DB

func InitDB() (*gorm.DB, error) {

	// db, err := gorm.Open("sqlite3", "./test1.db3")
	// db, err := gorm.Open("mysql", "root:123456@/test?charset=utf8&parseTime=True&loc=Asia/Shanghai")
	//db, err := gorm.Open("mysql", "root:123456@/go_test?charset=utf8")
	db, err := gorm.Open("mysql", system.GetConfiguration().MYSQL)

	checkErr(err)
	fmt.Println("init DB success!!!")

	//db.Exec(sql_table)//执行数据表
	if err == nil {
		DB = db
		db.LogMode(true)
		//db.AutoMigrate(&Page{}, &Post{}, &Tag{}, &PostTag{}, &User{}, &Comment{}, &Subscriber{}, &Link{}, &SmmsFile{})
		db.AutoMigrate(&Post{}, &Tag{}, &PostTag{}, &User{}, &Comment{}, &Page{} )
		//db.Model(&PostTag{}).AddUniqueIndex("uk_post_tag", "post_id", "tag_id")
		return db, err
	}
	return nil, err
}

// ==============Struct===============

type BaseModel struct {
	ID        uint `gorm:"primary_key"`
	CreatedAt time.Time
	UpdatedAt time.Time
}


type Tag struct {
	BaseModel
	Name  string
	Total int `gorm:"-"`//count of post
	IsView bool
}

// table post_tags
type PostTag struct {
	BaseModel
	PostId uint // post id
	TagId  uint // tag id
}









//===========func===============


//gorm-v1文档 https://v1.gorm.io/zh_CN/docs/
func ListPublishedPost(tag string, pageIndex, pageSize int) ([]*Post, error) {
	return _listPost(tag, true, pageIndex, pageSize)
}

func GetPostById(id string) (*Post, error) {
	pid, err := strconv.ParseUint(id, 10, 64)
	var post Post
	//err = DB.First(&post, "id=?", pid).Error
	err = DB.First(&post, pid).Error
	//fmt.Println(post)

	return &post, err
}

func (post *Post) UpdateView() error {
	//return DB.Model(post).Updates(map[string]interface{}{
	//	"view": post.View,
	//}).Error
	return DB.Model(&post).Update("view", post.View).Error
}

func CreatePost() *gorm.DB {

	return DB.Create(&Post{
		Title:       "wbz4",
		Body:        "xxx",
		IsPublished: true,
	})
}

func CountPostByTag(tag string) (count int, err error) {
	var (
		tagId uint64
	)
	if len(tag) > 0 {
		tagId, err = strconv.ParseUint(tag, 10, 64)
		if err != nil {
			return
		}
		err = DB.Raw("select count(*) from posts p inner join post_tags pt on p.id = pt.post_id where pt.tag_id = ? and p.is_published = ?", tagId, true).Row().Scan(&count)
	} else {
		err = DB.Raw("select count(*) from posts p where p.is_published = ?", true).Row().Scan(&count)
	}
	return
}



func checkErr(err error) {
	if err != nil {
		panic(err)
	}
}

//func CountPage() int {
//	var count int
//	DB.Model(&Page{}).Count(&count)
//	return count
//}

func MustListUnreadComment() []*Comment {
	comments, _ := ListUnreadComment()
	return comments
}

func ListUnreadComment() ([]*Comment, error) {
	var comments []*Comment
	err := DB.Where("read_state = ?", false).Order("created_at desc").Find(&comments).Error
	return comments, err
}


// str to uint
func StoUint(s string) (uint, error) {
	i, err := strconv.ParseUint(s, 10, 64)
	if err != nil {
		return 0, err
	}
	return uint(i), err
}

func MustListMaxReadPost() (posts []*Post) {
	posts, _ = ListMaxReadPost()
	return
}

func ListMaxReadPost() (posts []*Post, err error) {
	err = DB.Where("is_published = ?", true).Order("view desc").Limit(5).Find(&posts).Error
	return
}


func CountPage() int {
	var count int
	DB.Model(&Page{}).Count(&count)
	return count
}

func CountPost() int {
	var count int
	DB.Model(&Post{}).Count(&count)
	return count
}

func CountTag() int {
	var count int
	DB.Model(&Tag{}).Count(&count)
	return  count
}

func CountComment() int {
	var count int
	DB.Model(&Comment{}).Count(&count)
	return  count
}
